import User from '../../Models/User'

import * as jwt from 'jsonwebtoken'
import { SECRET_KEY } from '../../config'
// import { UserInputError } from '@apollo/server/errors'
import {
  validateRegisterInput,
  validateLoginInput,
} from '../../util/validators'
import * as bcrypt from 'bcrypt'
import { GraphQLError } from 'graphql'

export interface userInfo {
  id?: string,
  phone?: string,
  name?: string,
  username?: string,
  type?: string,
}
export interface RegisterForm {
  username: string
  phone: string
  name: string
  password: string
  email: string
  type: string
  confirmPassword: string
}
export interface RegisterInput {
  registerInput: RegisterForm
}
function generateToken(user: userInfo) {
  return jwt.sign(
    {
      id: user.id,
      phone: user.phone,
      name: user.name,
      username: user.username,
      type: user.type,
    },
    SECRET_KEY,
    { expiresIn: '1h' }
  )
}
export interface LoginQuery {
  username: string,
  password: string
}
const userResolvers = {
  Mutation: {
    async login(_: unknown, { username, password }: LoginQuery) {
      const errorMsg = validateLoginInput(username, password)
      if (errorMsg) {
        throw new GraphQLError(errorMsg, {
          extensions: {
            code: 'UserInputError',
          },
        });
        // throw new GraphQLError('Errors', error)
      }

      const user = await User.findOne({ username }).lean()
      if (!user) {
        throw new GraphQLError('User not found')
      }
      const match = await bcrypt.compare(password, user.password)
      if (!match) {
        throw new GraphQLError('ERROR Incorrect username or password')
      }
      const token = generateToken({ ...user, id: user._id.toString() })
      const data = {
        ...user,
        id: user._id,
        token,
      }
      return data
    },
    async register(
      _: any,
      { registerInput: { username, email, password, confirmPassword } } : RegisterInput
    ) {
      const errorMsg = validateRegisterInput(
        username,
        email,
        password,
        confirmPassword
      )
      if (errorMsg) {
        throw new GraphQLError(errorMsg)
      }
      const user = await User.findOne({ username })
      if (user) {
        throw new GraphQLError('username is taken')
      }
      password = await bcrypt.hash(password, 12)
      const newUser = new User({
        username,
        email,
        password,
        createdAt: new Date().toISOString(),
      })
      const res = await newUser.save()
      const token = generateToken(res)
      const data = {
        ...res,
        id: res._id,
        token,
      }
      return data
    },
  },
}
export { userResolvers }
